package cn.virens.web.components.session;

import java.time.Duration;

import org.springframework.cache.Cache;
import org.springframework.session.SessionRepository;
import org.springframework.util.Assert;

import cn.hutool.core.util.StrUtil;

/**
 * 使用Spring Cache 实现Spring Session 管理
 * 
 * @作者   : virens
 * @创建时间 :2018年1月15日 上午9:06:45
 */
public class SpringCacheSessionRepository implements SessionRepository<CacheSession> {

	public static final int DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS = 1800;
	public static final String DEFAULT_CACHE_NAME = "session-cache";

	private String cacheName = DEFAULT_CACHE_NAME;

	private org.springframework.cache.Cache mChache;
	private org.springframework.cache.CacheManager mCacheManager;

	private Duration maxInactiveInterval = Duration.ofSeconds(DEFAULT_MAX_INACTIVE_INTERVAL_SECONDS);

	public SpringCacheSessionRepository(org.springframework.cache.CacheManager mCacheManager) {
		this.mCacheManager = mCacheManager;
	}

	public String getCacheName() {
		return cacheName;
	}

	public void setCacheName(String cacheName) {
		this.cacheName = cacheName;
	}

	public Duration getMaxInactiveInterval() {
		return maxInactiveInterval;
	}

	public void setMaxInactiveInterval(Duration maxInactiveInterval) {
		this.maxInactiveInterval = maxInactiveInterval;
	}

	@Override
	public CacheSession createSession() {
		CacheSession result = new CacheSession();
		result.setMaxInactiveInterval(maxInactiveInterval);

		return result;
	}

	@Override
	public void save(CacheSession session) {
		String id = session.getId();

		if (!StrUtil.equals(id, session.getOriginalId())) {
			cache().evict(session.getOriginalId());

			session.setOriginalId(id);
		}

		cache().put(id, new CacheSession(session));
	}

	@Override
	public CacheSession findById(String id) {
		try {
			CacheSession saved = cache().get(id, CacheSession.class);
			if (saved == null) { return null; }

			if (saved.isExpired()) {
				this.deleteById(saved.getId());

				return null;
			}

			return new CacheSession(saved);
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public void deleteById(String id) {
		cache().evict(id);
	}

	private Cache cache() {
		if (mChache == null) {
			Assert.notNull(mCacheManager, "Cache Manage is null");

			this.mChache = mCacheManager.getCache(cacheName);
		}

		return this.mChache;
	}
}
